import random
from django.forms import widgets, fields, Form
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django_redis import get_redis_connection
from django.conf import settings
from app01 import models
from utils.tencent.sms import send_sms_single
from utils import encrypt
from app01.forms.bootstrapform import BootStrapForm

class RegisterForm(BootStrapForm, Form):
    username = fields.CharField(label='用户名', max_length=12, widget=widgets.TextInput, error_messages={'max_length': '用户名长度不能超过8位'})
    email = fields.EmailField(label='邮箱名', widget=widgets.EmailInput, error_messages={'invalid': '邮箱格式错误'})
    password = fields.CharField(label='密码', min_length=9, widget=widgets.PasswordInput, error_messages={'min_length': '密码长度不能小于9位'})
    confirm_password = fields.CharField(label='重复密码', widget=widgets.PasswordInput)
    phone_num = fields.CharField(label='手机号', validators=[RegexValidator(r'^1[13456789]\d{9}$', '手机格式错误')], widget=widgets.TextInput)
    code = fields.CharField(label='验证码', widget=widgets.TextInput)

    def clean_username(self):
        username = self.cleaned_data.get('username')
        exists = models.Userinfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('用户名已存在')
        return username

    def clean_email(self):
        email = self.cleaned_data.get('email')
        exists = models.Userinfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('此邮箱注册过')
        return email

    def clean_code(self):
        phone_num = self.cleaned_data.get('phone_num')
        code = self.cleaned_data.get('code')
        conn = get_redis_connection('default')
        value = conn.get(phone_num)
        if not value:
            raise ValidationError('验证已失效或手机号有变动')
        elif not code.strip() == value.decode('utf-8'):
            raise ValidationError('验证码不正确')
        return code

    def clean_password(self):
        password = self.cleaned_data.get('password')
        return encrypt.md5(password)

    def clean_confirm_password(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not password == encrypt.md5(confirm_password):
            raise ValidationError('两次密码不一致')
        return confirm_password

class LoginSmsForm(BootStrapForm, Form):
    phone_num = fields.CharField(label='手机号', validators=[RegexValidator(r'^1[3456789]\d{9}$', '手机格式错误'), ])
    code = fields.CharField(label='验证码', widget=widgets.TextInput)

    def clean_code(self):
        phone_num = self.cleaned_data.get('phone_num')
        code = self.cleaned_data.get('code')
        conn = get_redis_connection('default')
        value = conn.get(phone_num)
        if not value:
            raise ValidationError('验证码失效或手机号错了')
        elif not code.strip() == value.decode('utf-8'):
            raise ValidationError('验证码匹配不成功')
        return code

class LoginForm(BootStrapForm, Form):
    username = fields.CharField(label='用户名', widget=widgets.TextInput)
    password = fields.CharField(label='密码', widget=widgets.PasswordInput)
    code = fields.CharField(label='验证码', widget=widgets.TextInput)

    def __init__(self, request,*args, **kwargs):
        super().__init__(*args, *kwargs)
        self.request = request

    def clean_username(self):
        username = self.cleaned_data.get('username')
        exists = models.Userinfo.objects.filter(username=username).exists()
        if not exists:
            raise ValidationError('输入的用户名有误')
        return username

    def clean_password(self):
        password = self.cleaned_data.get('password')
        password_hashlib = encrypt.md5(password)
        exists = models.Userinfo.objects.filter(password=password_hashlib).exists()
        if not exists:
            raise ValidationError('输入的密码不正确')
        return password

    def clean_code(self):
        code = self.cleaned_data.get('code')
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码过期')
        if not session_code.strip().upper() == code.strip().upper():
            raise ValidationError('验证码输入不匹配')
        return code

class SmsForm(Form):
    phone_num = fields.CharField(validators=[RegexValidator(r'^1[3456789]\d{9}$', '手机格式错误'), ])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_phone_num(self):
        # 检测手机有没有注册过
        phone_num = self.cleaned_data.get('phone_num')
        exists = models.Userinfo.objects.filter(phone_num=phone_num).exists()
        template = self.request.POST.get('tpl')
        if template == 'login':
            if not exists:
                raise ValidationError('手机号没注册! 请注册后登录')
        elif exists:
            raise ValidationError('此手机号已注册')

        # 发送短信
        sms_template_id = settings.TENCENT_SMS_TEMPLATES.get(template)
        code = random.randrange(1000, 9999)
        res = send_sms_single(phone_num, sms_template_id, [code, ])
        if not res.get('result') == 0:
            raise ValidationError('短信发送失败,%s' % (res.get('errmsg'), ))

        # 把code写入Redis中去
        conn = get_redis_connection('default')
        conn.set(phone_num, code, ex=60)
        return phone_num


